package com.cutter.demo;

import com.cutter.util.FFmpegMerge;

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class MergeVideo {
    static String tpath = "G:\\testResource\\test";
    static String mergedVideoName = "merged";
    static String mergedVideoPath;
    static Integer videos = 5;
    static boolean rename = false;
    static boolean delete = false;
    static String newNamePre="video";
    static String originFileNamePattern = ".*P(\\d+).*(\\.mp4)$";

    public static void main(String[] args) {
        if (args.length==0){
            // 未输入参数进入交互模式
            interactive();
        }
        else if (args.length==1){
            // 输入路径快速合并
            tpath = args[0];
            mergedVideoPath = tpath;
            startMerging();
        }
    }
    private static void interactive() {
        Scanner scan = new Scanner(System.in);
        System.out.printf("请输入源视频文件名格式(正则表达 默认[%s]):\n",originFileNamePattern);
        String pattern = scan.nextLine();
        if (pattern!=null&&pattern.trim().length()>0){originFileNamePattern=pattern;}
        System.out.println("请输入源视频源文件路径:");
        tpath = checkPathInput(scan);
        System.out.println("目标视频文件路径(默认源视频路径):");
        String mergedVideoPathInput = checkPathInputDefault(scan);
        mergedVideoPath = "default".equals(mergedVideoPathInput)?tpath:mergedVideoPathInput;
        System.out.println("目标视频名前缀(默认merged):");
        String outputFileName = scan.nextLine();
        if (outputFileName!=null&&outputFileName.trim().length()>0){mergedVideoName=outputFileName;}
        System.out.println("是否对源文件改名(源文件改名可提高合并成功率) 改名输入y");
        if ("y".equals(scan.nextLine())){
            rename = true;
            System.out.println("请输入新文件名前缀(默认video):");
            newNamePre = checkNewNameInput(scan);
        }
        System.out.println("输入合并到一起的视频数量(默认5):");
        String videoCount = scan.nextLine();
        if (videoCount!=null&&videoCount.trim().length()>0){videos=Integer.parseInt(videoCount);}
        System.out.println("完成后是否删除源文件(默认不删除) 输入y确认");
        if ("y".equals(scan.nextLine())){
            delete = true;
        }
        startMerging();
    }
    public static void startMerging(){
        List<List<String>> videosToMerge = MergeVideo.getVideosToMerge(tpath,videos);
        if (videosToMerge==null)return;
        AtomicInteger n = new AtomicInteger(0);
        List<String> sourceList = new ArrayList<>();
        videosToMerge.forEach(
                (f)->{
                    String s = FFmpegMerge.makeVideosNameFile(f, tpath,n.get());
                    if (s==null)return;
                    int newIndex = getNewIndex(s, n.get());
                    n.set(newIndex);
                    sourceList.add(s);
                }
        );
        n.set(0);
        sourceList.forEach(
                (sourceInfoFile)->{
                    String s = FFmpegMerge.mergeDirect(sourceInfoFile,
                            mergedVideoPath, mergedVideoName, n.get());
                    int newIndex = getNewIndex(s, n.get());
                    n.set(newIndex);
                }
        );
        if (delete){
            System.out.println("删除源文件.....");
            videosToMerge.forEach(f-> f.forEach(f1->{
                                    File file = new File(f1);
                                    if (file.exists()&&file.isFile()){
                                        file.delete();
                                    }}));
        }
    }
    public static List<List<String>> getVideosToMerge(String videoPath,int videoCount){
        File pathVideo = new File(videoPath);
        if (!pathVideo.exists()||!pathVideo.isDirectory()){
            return null;
        }
        File[] videoFiles = pathVideo.listFiles((dir, name) -> {
            String namePattern = originFileNamePattern;
            return Pattern.matches(namePattern, name);
        });
        if (videoFiles==null||videoFiles.length==0){
            System.out.println("no video available");
            return null;
        }
        if (rename){
            videoFiles = renameOriginFile(videoFiles,newNamePre);
        }
        List<String> videoFileNameList =
                Arrays.stream(videoFiles).
                sorted(Comparator.comparingInt(file -> getSortOrder(file.getName()))).
                map(File::getAbsolutePath).collect(Collectors.toList());
        List<List<String>> result = new ArrayList<>();
        int size = videoFileNameList.size();
        int time = size/videoCount +1 ;
        for (int i = 0; i < time; i++) {
            int beginIndex = i*videoCount;
            int endIndex = beginIndex + videoCount;
            if (endIndex >= size){endIndex = size;}
            List<String> list = videoFileNameList.subList(beginIndex, endIndex);
            result.add(list);
        }
        return result;
    }
    private static File[] renameOriginFile(File[] videoFiles, String newNamePre) {
        String namePattern = originFileNamePattern;
        File[] resFiles = new File[videoFiles.length];
        for (int i=0;i<videoFiles.length;i++) {
            resFiles[i]=videoFiles[i];
            Pattern pattern = Pattern.compile(namePattern);
            String originFileName = videoFiles[i].getName();
            Matcher matcher = pattern.matcher(originFileName);
            if (matcher.find()){
                String sortOrder = matcher.group(1);
                String suffix = matcher.group(2);
                String newName = newNamePre + sortOrder + suffix;
                File file = new File(videoFiles[i].getParent() + File.separator + newName);
                if (videoFiles[i].renameTo(file)){
                    resFiles[i]=file;
                }
            }
        }
        originFileNamePattern = getNewNamePattern(newNamePre);
        return resFiles;
    }
    public static int getSortOrder(String fileName){
        String namePattern = originFileNamePattern;
        Pattern pattern = Pattern.compile(namePattern);
        Matcher matcher = pattern.matcher(fileName);
        if (matcher.find()){
            String orderStr = matcher.group(1);
            return Integer.parseInt(orderStr);
        }else {
            return -1;
        }
    }
    public static int getNewIndex(String returnStr,int oldIndex){
        int i = returnStr.lastIndexOf('_');
        if (i!=-1){
            StringBuilder sb = new StringBuilder();
            for (int j = i+1; j < returnStr.length(); j++) {
                int ascii = returnStr.charAt(j);
                if (ascii>=48&&ascii<=57){
                    sb.append((char) ascii);
                }else {break;}
            }
            Integer resN = Integer.valueOf(sb.toString());
            return resN.equals(oldIndex)?oldIndex+1:resN+1;
        }else {
            return oldIndex+1;
        }

    }
    public static String checkPathInput(Scanner scan){
        while (true){
            String filePath = scan.nextLine();
            if ("q".equals(filePath)){System.exit(-1);return null;}
            File sour = new File(filePath);
            if (sour.exists()&&sour.isDirectory()){return sour.getAbsolutePath();}
            else {
                System.out.println("输入文件路径不存在或不正确,请再次输入");
            }
        }
    }
    public static String checkPathInputDefault(Scanner scan){
        while (true){
            String filePath = scan.nextLine();
            if ("q".equals(filePath)){
                System.exit(-1);
                return null;}
            else if (filePath==null||filePath.trim().length()==0){
                return "default";
            }else {
                File sour = new File(filePath);
                if (sour.exists()&&sour.isDirectory()){return sour.getAbsolutePath();}
                else {
                    System.out.println("输入文件路径不存在或不正确,请再次输入");
                }
            }
        }
    }
    public static String getNewNamePattern(String newNamePre){
        int i = originFileNamePattern.indexOf('(');
        String newNamePattern = originFileNamePattern;
        if (i!=-1){
            newNamePattern = newNamePre + originFileNamePattern.substring(i);
        }
        return newNamePattern;
    }
    public static String checkNewNameInput(Scanner scan){
        while (true){
            String newNameP = scan.nextLine();
            if (newNameP==null||newNameP.trim().length()==0){
                newNameP = newNamePre;
            }
            if (newNameP.equals(mergedVideoName)&&mergedVideoPath.equals(tpath)){
                System.out.println("同文件路径输出时,改名后视频不可与合并后输出视频同名!");
            }else {return newNameP;}
        }
    }
}
